﻿using System;
using System.Collections.Generic;
using System.Drawing;
using RaytracerLib.Layers;
using RaytracerLib.MathLib;
using TomanuExtensions;
using RaytracerLib.Layers.OverlayCorrectors;
using System.Linq;
using RaytracerLib.Postprocessing;
using System.Diagnostics;
using RaytracerLib.Renderers;

namespace RaytracerLib.Resamplers
{
    public class ExactResampler : InterpolateResampler
    {
        public bool SuppressLog = false;

        protected int m_rays_counter = 0;

        internal override void SetRayColor(Vector2 a_pixel, ColorFloat a_color)
        {
            a_color = Gamma.LinearToSRGB(a_color);

            int start_x = (int)Math.Floor(a_pixel.X - Filter.Ray);
            int end_x = (int)Math.Ceiling(a_pixel.X + Filter.Ray) - 1;

            int start_y = (int)Math.Floor(a_pixel.Y - Filter.Ray);
            int end_y = (int)Math.Ceiling(a_pixel.Y + Filter.Ray) - 1;

            for (int y = start_y; y <= end_y; y++)
            {
                int cy = m_overlay_corrector.CorrectY(y);
                double wy = Filter.Evaluate((y + 0.5) - a_pixel.Y);

                for (int x = start_x; x <= end_x; x++)
                {
                    int cx = m_overlay_corrector.CorrectX(x);
                    double wx = Filter.Evaluate((x + 0.5) - a_pixel.X);

                    m_pixels[cx, cy].Collect(a_color, wy * wx);
                }
            }

            m_rays_counter++;

            Debug.Assert(Filter.Evaluate(a_pixel.X - (start_x + 0.5 - 1)).IsAlmostEquals(0));
            Debug.Assert(Filter.Evaluate(a_pixel.X - (end_x + 0.5 + 1)).IsAlmostEquals(0));
            Debug.Assert(Filter.Evaluate(a_pixel.Y - (start_y + 0.5 - 1)).IsAlmostEquals(0));
            Debug.Assert(Filter.Evaluate(a_pixel.Y - (end_y + 0.5 + 1)).IsAlmostEquals(0));
        }

        public override ResamplerType ResamplerType
        {
            get
            {
                return ResamplerType.Exact;
            }
        }

        internal override void RenderEnd()
        {
            base.RenderEnd();

            if (!SuppressLog)
            {
                double avg = (double)m_rays_counter / (Film.Width * Film.Height);

                if (Film.Scene.RenderOptions.Renderer is SamplesVisualizerRenderer)
                {
                    int scale = (Film.Scene.RenderOptions.Renderer as SamplesVisualizerRenderer).Scale;
                    avg *= scale * scale;
                }

                Loggers.Raytracer.Info("Average rays per pixels: {0}", avg);
            }
        }
    }
}